﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;

using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using Newtonsoft.Json;
using System.Runtime.InteropServices;
using System.Collections;
using System.Diagnostics;
using server.Model;

namespace server
{
    [System.Runtime.InteropServices.ComVisible(true)]

    public partial class Form1 : Form
    {
        //保存所有车辆的坐标信息
        public List<GPSMessage> Loc = new List<GPSMessage>();
        //保存所有接收的消息
        public List<UDPMessage> Rec = new List<UDPMessage>();
        //创建一个监听消息的线程
        private Thread threadWatch = null;
        private Thread threadview = null;
        //用于保存所有通信客户端的Socket
        private Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
        //本地ip端口
        private IPEndPoint endpoint = null;
        //创建接收盒子消息的套接字参数
        private IPAddress clientIP = IPAddress.Parse("192.168.10.224"); //访问盒子的IP
        private int clientPort = 40000; //访问盒子的端口号
        private EndPoint Remote;
        private Socket socketWatch = null;
        //创建发送盒子消息的套接字参数
        private int sendport = 50000;
        private IPEndPoint sendpoint = null;
        private EndPoint sendRemote;
        private Socket socketSend = null;

        public Form1()
        {
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            baidumap_Load();
            //关闭对文本框的非法线程操作检查
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }

        /// <summary>
        /// 加载系统地图，使用百度地图API
        /// </summary>
        private void baidumap_Load()
        {
            string str_url = Application.StartupPath + "/baidumap.html";
            Uri url = new Uri(str_url);
            webBrowser1.Url = url;
            webBrowser1.ObjectForScripting = this;
        }

        /// <summary>
        /// 开启服务端，启动监测客户端链接的线程
        /// </summary>
        //public delegate void DelUserHandler();
        private void button2_Click(object sender, EventArgs e)
        {

            //定义一个套接字用于监听客户端发来的信息包含3个参数(IP4寻址协议,流式连接,UDP协议)
            socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPAddress ipAddress = IPAddress.Parse("192.168.10.200"); //GetLocalIPv4Address();
            int port = 40000;
            endpoint = new IPEndPoint(ipAddress, port);
            //绑定网络地址
            socketWatch.Bind(endpoint);
            
            //发送消息
            sendpoint = new IPEndPoint(ipAddress, sendport);
            IPEndPoint accept = new IPEndPoint(clientIP, sendport);
            sendRemote = (EndPoint)(accept);
            
            //定时更新显示
            threadview = new Thread(Dowork);
            threadview.IsBackground = true;
            threadview.Start();

            threadWatch = new Thread(WatchConnecting);
            threadWatch.IsBackground = true;
            threadWatch.Start();
            sendmsg.AppendText("TA端开始监测！" + "\r\n");
            msglist.Items.Add("时间                 认证   消息");
            butstart.Enabled = false;            
        }

        /// <summary>
        /// 获取本地IPv4地址
        /// </summary>
        /// <returns>本地IPv4地址</returns>
        public IPAddress GetLocalIPv4Address()
        {
            IPAddress localIPv4 = null;
            IPAddress[] ipAddressList = Dns.GetHostAddresses(Dns.GetHostName());
            foreach (IPAddress ipAddress in ipAddressList)
            {
                //判断是否是IPv4地址
                if (ipAddress.AddressFamily == AddressFamily.InterNetwork) //AddressFamily.InterNetwork表示IPv4 
                {
                    localIPv4 = ipAddress;
                    //test-weber
                    break;
                }
                else
                    continue;
            }
            return localIPv4;
        }

        /// <summary>
        /// 将GPSMessage加入List
        /// </summary>
        /// <param name="gps"></param>
        public void AddGPS(GPSMessage gps)
        {
            for (int i = 0; i < Loc.Count; ++i)
            {
                if (Loc[i].UserID.Equals(gps.UserID))
                {
                    Loc[i].LocX = gps.LocX;
                    Loc[i].LocY = gps.LocY;
                    Loc[i].Time = gps.Time;
                    return;
                }
            }
            Loc.Add(gps);
            return;
        }

        string str = null;
        /// <summary>
        /// 持续不断监听客户端发来的请求, 用于不断获取客户端发送过来的连续数据信息
        /// </summary>
        private void WatchConnecting()
        {
            
            //创建访问盒子的唯一标识 由IP和端口号组成 
            IPEndPoint sender = new IPEndPoint(clientIP, clientPort);
            Remote = (EndPoint)(sender);
            int length = 0;
            while (true)
            {
                
                //创建一个接收用的内存缓冲区 大小为10M字节数组
                byte[] arrServerRecMsg = new byte[10 * 1024 * 1024];
                length = socketWatch.ReceiveFrom(arrServerRecMsg, ref Remote);//消息格式：[用户名] [count] A 数据
                Encoding encoding = System.Text.Encoding.GetEncoding("UTF-8");
                str = encoding.GetString(arrServerRecMsg, 0, length);
                string[] strs = str.Split(new char[] {' '});
                if (strs[2] == "V")             //他车GPS消息
                {
                    GPSMessage gpsva = new GPSMessage(strs[0], double.Parse(strs[6]), double.Parse(strs[4]), DateTime.Now);
                    AddGPS(gpsva);

                    //jsontest = JsonConvert.SerializeObject(Loc, Formatting.Indented);
                    //webBrowser1.Document.InvokeScript("move", new object[] { jsontest });
                }

                /*if (strs[0] == "V")              //本地GPS消息
                {
                    GPSMessage gpsva = new GPSMessage("TA", double.Parse(strs[4]), double.Parse(strs[2]), DateTime.Now);
                    AddGPS(gpsva);

                }*/

                if (strs[2] == "A")             //UDP文本消息
                {

                    int i = strs[0].Length + strs[1].Length + strs[2].Length + 3;
                    string content = str.Substring(i);

                    //json消息格式
                    VANETMessage message = new VANETMessage(content);
                    string content_senderName = message.senderName;
                    string content_msg = message.msg;
                    string content_msg_sign = message.msg_sign;
                    string content_PseID_1 = message.PseID_1;
                    string content_PseID_2 = message.PseID_2;

                    string msg_sign_base64 = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(content_msg_sign));
                    string Pse_ID_1_base64 = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(content_PseID_1));
                    string Pse_ID_2_base64 = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(content_PseID_2));
                    string msg_base64 = Convert.ToBase64String(Encoding.GetEncoding("UTF-8").GetBytes(content_msg));
            

                    //process外部程序
                    Process myProcess = new Process();
                    string filename = "pbc.exe";
                    string para = "a.param " + msg_sign_base64.Replace("\r\n", "") + " " + Pse_ID_1_base64.Replace("\r\n", "")
                                  + " " + Pse_ID_2_base64.Replace("\r\n", "") + " " + msg_base64.Replace("\r\n", "");
                    ProcessStartInfo Info = new ProcessStartInfo(filename, para);
                    Info.UseShellExecute = false;
                    Info.RedirectStandardOutput = true;
                    Info.CreateNoWindow = true;
                    Info.WindowStyle = ProcessWindowStyle.Hidden;
                    myProcess.StartInfo = Info;
                    myProcess.Start();
                    while (!myProcess.HasExited)
                    {
                        myProcess.WaitForExit();
                    }
                    string value = myProcess.StandardOutput.ReadToEnd();
                    myProcess.Close();
                    
                    string[] value_str = value.Split(new char[] { ' ' });
                    UDPMessage Rec_Msg = new UDPMessage(content_msg, value_str[0], value_str[1],GetCurrentTime());
                    int Rec_para = 0;
                    for (int j = 0; j<Rec.Count(); j++)
                    {
                        TimeSpan Timegap = Rec_Msg.Msg_Time - Rec[j].Msg_Time;
                        if (Timegap.TotalSeconds < 1)
                        {
                            Rec_para = 1;
                        } 
                    }
                    if(Rec_para == 0)
                    {
                        Rec.Add(Rec_Msg);
                        msglist.Items.Add(Rec_Msg.Msg_Time + "  " + Rec_Msg.Auth + "  " +Rec_Msg.Message);
                    }
                    
                }
            }
        }

        /// <summary>
        /// 发送信息到车辆的方法
        /// </summary>
        /// <param name="sendMsg">发送的字符串信息</param>
        private void ServerSendMsg(string sendMsg)
        {
            if (string.IsNullOrEmpty(txtSendMsg.Text.Trim()))
                return;
            if (butstart.Enabled != false)
            {
                sendmsg.AppendText("请先启动服务！！\n");
                txtSendMsg.Text = null;
                return;
            }
            socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socketSend.Bind(sendpoint);
            string Msg = Convert.ToBase64String(Encoding.UTF8.GetBytes(txtSendMsg.Text.Trim()));

            VANETMessage Send_Message = new VANETMessage();
            Send_Message.senderName = "siri";
            Send_Message.msg = Msg;
            string Send_Message_json = Send_Message.tostring();
         
            byte[] arrSendMsg = null;
            sendMsg = "A" + " "+ "[ALL]" + " " + Send_Message_json;
            //将输入的字符串转换成机器可以识别的字节数组
            arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
            //通过Socket的SendTo方法将字节数组发送出去
            socketSend.SendTo(arrSendMsg, arrSendMsg.Length, SocketFlags.None, sendRemote);
            sendmsg.AppendText("您在" + GetCurrentTime() + "向所有车辆发送了:\r\n" + txtSendMsg.Text.Trim() + "\r\n");
            
            socketSend.Close();
            txtSendMsg.Text = null;
        }
        /// <summary>
        /// 发送信息
        /// </summary>
        private void butsend_Click(object sender, EventArgs e)
        {
            ServerSendMsg(txtSendMsg.Text);
        }
        /// <summary>
        /// 清空提示内容
        /// </summary>
        public int txtSend_para = 1;
        private void txtSendMsg_MouseClick(object sender, MouseEventArgs e)
        {
            if (txtSend_para == 1)
            {
                txtSendMsg.Text = null;
                txtSend_para = 0;
            }
        }
        /// <summary>
        /// 快捷键 Enter 发送信息
        /// </summary>
        private void txtSendMsg_KeyDown(object sender, KeyEventArgs e)
        {
            ////当光标位于输入文本框上的情况下 发送信息的热键为回车键Enter
            if (e.KeyCode == Keys.Enter)
            {
                //则调用 服务器向客户端发送信息的方法 
                ServerSendMsg(txtSendMsg.Text);
            }
        }

        /// <summary>
        /// 获取当前系统时间
        /// </summary>
        /// <returns>当前系统时间</returns>
        public DateTime GetCurrentTime()
        {
            DateTime currentTime = new DateTime();
            currentTime = DateTime.Now;
            return currentTime;
        }

        /// <summary>
        /// 关闭服务端
        /// </summary>
        private void butexit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        public string json = null;
        /// <summary>
        /// 通过委托，与前端传递位置信息
        /// </summary>
        /// <param name="str">STR中包含经纬度，解析后可获得</param>
        private List<GPSMessage> LocShow()
        {
            List<GPSMessage> reLocShow = new List<GPSMessage>();
            for (int i = 0; i < Loc.Count; ++i)
            {
                TimeSpan LocTime = DateTime.Now - Loc[i].Time;
                if (LocTime.TotalSeconds < 5)
                {
                    reLocShow.Add(Loc[i]);
                }
            }
            return reLocShow;
        }
        delegate void deledocm();
        public void work()
        {
            if (webBrowser1.InvokeRequired)
            {
                deledocm d = new deledocm(docm);
                this.BeginInvoke(d);
            }
            else { docm(); }
        }
        public void docm()
        {
            List<GPSMessage> reLocShow = LocShow();
            json = JsonConvert.SerializeObject(reLocShow, Formatting.Indented);
            webBrowser1.Document.InvokeScript("move", new object[] { json });
            carnum.Text = ""+reLocShow.Count;
        }
        private void Dowork()
        {
            while (true)
            { 
                work();
                //Loc.Clear();
                Thread.Sleep(3000);
            }
        }
        /// <summary>
        /// 车辆注册
        /// </summary>
        private void buttonLogin_Click(object sender, EventArgs e)
        {
            Login logim_form = new Login();
            logim_form.Show();
        }

        /// <summary>
        /// 已注册车辆
        /// </summary>
        private void button2_Click_1(object sender, EventArgs e)
        {
            CarList CarList_form = new CarList();
            CarList_form.Show();
        }
        /// <summary>
        /// 追溯消息
        /// </summary>
        private void tracebutton_Click(object sender, EventArgs e)
        {
            
            if (msglist.SelectedItem != null)
            {
                string msg_selected = msglist.SelectedItem.ToString();
                string[] strs_selected = msg_selected.Split(new char[] { ' ' });
                if (strs_selected[0] != "时间")
                {
                    string msg_time = strs_selected[0] + " " + strs_selected[1];
                    for (int i = 0; i < Rec.Count; ++i)
                    {
                        if (Rec[i].Msg_Time.ToString().Equals(msg_time))
                        {
                            string trace_RID = Rec[i].RID;
                            VanetRIDal trace_VRD = new VanetRIDal();
                            string trace_licence = trace_VRD.GetbyRID_trans(trace_RID);
                            trace trace_form = new trace(trace_licence);
                            trace_form.Show();
                            return;
                        }
                    }
                }
            }
        }
    }
}
